跳到主要内容

[toc]

awk BEGIN模式、END模式

BEGIN模式

说明

BEGIN 模式在awk程序执行后,但尚未执行处理动作之前需要做的工作(定义变量)

作用

作用一 打印标题

文件 a.txt 内容如下

101,abc,CEO
102,def,CTO
103,qaz,COO

默认打印

$ awk '{print}' a.txt
101,abc,CEO
102,def,CTO
103,qaz,COO

使用 BEGIN 模式打印标题

$ awk 'BEGIN{print "ID","name","job"}{print}' a.txt 
ID name job
101,abc,CEO
102,def,CTO
103,qaz,COO

作用二 做运算

示例1:计算1到100的和

$ awk 'BEGIN{for(i=1;i<=100;i++) sum+=i;print sum}'
5050

示例2:普通计算

# 加法
$ awk 'BEGIN{print 3+3}'
6

# 减法
$ awk 'BEGIN{print 3-3}'
0

# 乘法
$ awk 'BEGIN{print 3*3}'
9

# 除法
$ awk 'BEGIN{print 3/3}'
1

# 幂运算
$ awk 'BEGIN{print 3**3}'
27

# 取模
$ awk 'BEGIN{print 3%3}'
0

作用三 修改awk内置变量

  • record 字段

  • separator 分隔符

变量名对应单词含义
FSfield separator字段分隔符,默认空格或 tab
OFSoutput field separator输出分隔符,默认空格
RSrecord separator记录分隔符,默认换行符 \n
ORSoutput record separator输出记录分隔符
FS 指定字段分隔符

passwd.txt 文件内容如下

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

示例:以冒号为分隔符,打印文件第一列

$ awk 'BEGIN{FS=":"}{print $1}' passwd.txt 
root
bin
daemon
OFS 指定输出分隔符

文件 a.txt 内容如下

1 2 3
a b c
D F 6

示例:打印文件第一列和第三列,以冒号为分隔符

注意

-v OFS 写法的一个坑:当 print $0 的时候,-v OFS 会不生效

$ awk -v OFS=: '{print $0}' a.txt 
1 2 3
a b c
D F 6

解决方法是在 print$0 前加一个 $1=$1

$ awk -v OFS=: '{$1=$1;print $0}' a.txt 
1:2:3
a:b:c
D:F:6
$ awk -v OFS=: '{print $1,$3}' a.txt 
1:3
a:c
D:6
RS 指定记录分隔符,即指定以什么为分隔符,默认为 \n

passwd.txt 文件内容如下,文件默认以换行为记录分隔符

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

示例:将文件的记录分隔符指定为 / ,即指定文件以 / 为换行符

$ awk -v RS=/ '{print $0}' passwd.txt 
root:x:0:0:root:
root:
bin
bash
bin:x:1:1:bin:
bin:
sbin
nologin
daemon:x:2:2:daemon:
sbin:
sbin
nologin

ORS 指定输出记录分隔符

文件 a.txt 内容如下

1 2 3
a b c
D F 6

示例:将文件的输出记录分隔符指定为 /

$ awk -v ORS="/" '{print $0}' a.txt
1 2 3/a b c/D F 6/

扩展 awk命令行参数

说明
  • ARGC 是命令行参数数量

  • ARGV 是将命令行参数存到数组,元素由 ARGC 指定,数组下标从 0 开始

ARGC

说明
  • ARGCawk 的内置变量,表示 命令行参数的数量Argument Count),包括 awk 命令本身
  • 在这个例子中,awk 命令本身是第一个参数(awk),但 ARGCBEGIN 块中统计的是 awk 处理的参数数量(不包括选项和程序代码)
  • 由于没有提供输入文件(如 awk 'BEGIN{print ARGC}' file.txt),ARGC 的值为 1(仅包含 awk 命令本身)
$ awk 'BEGIN{print ARGC}'
1
说明
  • BEGIN 块中,ARGC 已经计算完毕,但 awk 还没有开始处理输入文件(如果有的话)
  • 这里的 12 会被 awk 视为输入文件(即使它们不是有效的文件名),但 BEGIN 块在读取文件之前执行,所以 ARGC 只计算参数数量
$ awk 'BEGIN{print ARGC}' 1 2
3

对比

  • 如果运行 awk 'BEGIN{print ARGC}' file1 file2(假设 file1file2 存在),输出也是 3awk + file1 + file2
  • 如果运行 awk 'BEGIN{print ARGC}'(无额外参数),输出是 1(只有 awk 命令本身)

ARGV

说明
  • ARGV[0]awk(命令本身)
  • ARGV[1]1(第一个额外参数)
  • ARGV[2]2(第二个额外参数)
$ awk 'BEGIN{print ARGV[0]}' 1 2
awk

$ awk 'BEGIN{print ARGV[1]}' 1 2
1

$ awk 'BEGIN{print ARGV[2]}' 1 2
2

END模式

说明

END 模式在 awk 读取完文件之后执行,主要作用为显示计算结果

作用 显示计算结果

示例1:统计 /etc/passwd 文件中前10行非登陆shell的个数

文件内容

$ head /etc/passwd
root:x:0:0:Super User:/root:/bin/bash
bin:x:1:1:bin:/bin:/usr/sbin/nologin
daemon:x:2:2:daemon:/sbin:/usr/sbin/nologin
adm:x:3:4:adm:/var/adm:/usr/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/usr/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/usr/sbin/nologin
operator:x:11:0:operator:/root:/usr/sbin/nologin

统计文件中 /sbin/nologin 的个数

$ head /etc/passwd | awk '/nologin/{i++}END{print i}'
6

示例2:统计 /etc/services 中空行数量

$ awk '/^$/{i++}END{print i}' /etc/services
17

示例3:统计nginx访问日志中访问量前10的IP

$ awk '{a[$1]++}END{for(i in a) print a[i],i}' /var/log/nginx/access.log|sort -nr|head
275 1.1.1.1
262 2.2.2.2
210 3.3.3.3
152 4.4.4.4
75 5.5.5.5
10 6.6.6.6
7 7.7.7.7
6 8.8.8.8
3 9.9.9.9
3 10.10.10.10
Right Bottom Gif
Right Top GIF